home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / HPACK78S.ZIP / viewfile.c < prev    next >
C/C++ Source or Header  |  1992-12-03  |  14KB  |  470 lines

  1. /****************************************************************************
  2. *                                                                            *
  3. *                            HPACK Multi-System Archiver                        *
  4. *                            ===========================                        *
  5. *                                                                            *
  6. *                       Display the Contents of an Archive                    *
  7. *                          VIEWFILE.C  Updated 12/07/92                        *
  8. *                                                                            *
  9. * This program is protected by copyright and as such any use or copying of    *
  10. *  this code for your own purposes directly or indirectly is highly uncool    *
  11. *                      and if you do so there will be....trubble.                *
  12. *                 And remember: We know where your kids go to school.            *
  13. *                                                                            *
  14. *        Copyright 1989 - 1992  Peter C.Gutmann.  All rights reserved        *
  15. *                                                                            *
  16. ****************************************************************************/
  17.  
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #ifdef __MAC__
  21.   #include "defs.h"
  22.   #include "arcdir.h"
  23.   #include "choice.h"
  24.   #include "error.h"
  25.   #include "flags.h"
  26.   #include "frontend.h"
  27.   #include "hpacklib.h"
  28.   #include "hpaktext.h"
  29.   #include "system.h"
  30.   #include "wildcard.h"
  31.   #include "fastio.h"
  32.   #include "hpackio.h"
  33.   #include "tags.h"
  34. #else
  35.   #include "defs.h"
  36.   #include "arcdir.h"
  37.   #include "choice.h"
  38.   #include "error.h"
  39.   #include "flags.h"
  40.   #include "frontend.h"
  41.   #include "hpacklib.h"
  42.   #include "system.h"
  43.   #include "wildcard.h"
  44.   #include "io/fastio.h"
  45.   #include "io/hpackio.h"
  46.   #include "language/hpaktext.h"
  47.   #include "tags.h"
  48. #endif /* __MAC__ */
  49.  
  50. /* Prototypes for functions in ARCHIVE.C */
  51.  
  52. int extractData( const WORD dataInfo, const BYTE extraInfo, \
  53.                  LONG dataLen, const LONG fileLen, const BOOLEAN isFile );
  54.  
  55. #ifdef __MSDOS__
  56.  
  57. /* Prototypes for functions in MISC.ASM */
  58.  
  59. int getRatio( long dataLen, long compressedLen );
  60. #endif /* __MSDOS__ */
  61.  
  62. /****************************************************************************
  63. *                                                                            *
  64. *                            Display Contents of Archive                        *
  65. *                                                                            *
  66. ****************************************************************************/
  67.  
  68. /* The names of the OS's. */
  69.  
  70. const char *systemName[] = { "MSDOS", "UNIX ", "Amiga", " Mac ",
  71.                              " Arc ", "OS/2 ", "IIgs ", "Atari",
  72.                              " VMS ", "Prime", "?????" };
  73.  
  74. /* What format to print the date in */
  75.  
  76. enum { DATE_MDY, DATE_DMY, DATE_YMD, DATE_MYD, DATE_DYM, DATE_YDM };
  77.  
  78. int dateFormat;        /* Which of the above date formats to use */
  79.  
  80. /* Determine the format to print the date in */
  81.  
  82. void setDateFormat( void )
  83.     {
  84.     dateFormat = getCountry();
  85.     }
  86.  
  87. #ifdef __MSDOS__
  88.   void extractDate( const LONG time, int *time1, int *time2, int *time3, \
  89.                                      int *hours, int *minutes, int *seconds );
  90. #else
  91.  
  92. /* Constants for time handling functions */
  93.  
  94. #define SECS_PER_DAY    86400L
  95. #define DAYS_PER_YEAR    365
  96. #define MONTHS_PER_YEAR    12
  97. #define FEB29            60        /* Days to Feb.29 from start of year */
  98. #define AD2000            30        /* Year count to 2000AD */
  99.  
  100. /* Lookup table for month lengths */
  101.  
  102. int monthLen[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
  103.  
  104. /* Extract the date fields from the time value.  A custom version is used
  105.    since there is some confusion with different versions of localtime()
  106.    making strange adjustments for what they think is local time */
  107.  
  108. void extractDate( LONG time, int *time1, int *time2, int *time3, \
  109.                              int *hours, int *minutes, int *seconds )
  110.     {
  111.     int days, months, years, leapYearOffset = 0;
  112.  
  113.     /* Extract date/time */
  114.     days = ( int ) ( time / SECS_PER_DAY );
  115.     time %= SECS_PER_DAY;
  116.  
  117.     /* Extract hours, minutes, seconds */
  118.     *seconds = ( int ) ( time % 60 );
  119.     time /= 60;
  120.     *hours = ( int ) ( time / 60 );
  121.     *minutes = ( int ) ( time % 60 );
  122.  
  123.     /* Extract days, months, years */
  124.     years = days / DAYS_PER_YEAR;
  125.     days = ( ( days % DAYS_PER_YEAR ) + 1 ) - ( years / 4 );
  126.  
  127.     /* Check for underflow due to leap years */
  128.     if( days <= 0 )
  129.         {
  130.         /* Move back 1 year and adjust days to December */
  131.         years--;
  132.         days += DAYS_PER_YEAR;
  133.         }
  134.  
  135.     /* Check for leap year extra day - need to adjust if year count (adjusted
  136.        to base of 1972) is divisible by 4, if it's not 2000AD, and if it's
  137.        past Feb.29 */
  138.     if( !( ( years + 2 ) & 3 ) && years != AD2000 && days >= FEB29 )
  139.         {
  140.         days--;                /* Subtract day for Feb.29 */
  141.         leapYearOffset++;    /* Remember extra day later on */
  142.         }
  143.  
  144.     /* Evaluate month days */
  145.     months = MONTHS_PER_YEAR - 1;
  146.     while( days <= monthLen[ months ] )
  147.         months--;
  148.     days -= monthLen[ months ] + leapYearOffset;
  149.     months++;        /* Convert offset from 0 -> 1 */
  150.     years = ( years + 70 ) % 100;
  151.  
  152.     /* Reorder fields depending on country */
  153.     switch( dateFormat )
  154.         {
  155.         case DATE_DMY:
  156.             /* Use DD/MM/YY format */
  157.             *time1 = days;
  158.             *time2 = months;
  159.             *time3 = years;
  160.             break;
  161.  
  162.         case DATE_YMD:
  163.             /* Use YY/MM/DD format */
  164.             *time1 = years;
  165.             *time2 = months;
  166.             *time3 = days;
  167.             break;
  168.  
  169.         default:
  170.             /* Use MM/DD/YY format */
  171.             *time1 = months;
  172.             *time2 = days;
  173.             *time3 = years;
  174.         }
  175.     }
  176. #endif /* __MSDOS__ */
  177.  
  178. /* Format a filename to fit the screen size */
  179.  
  180. static char *formatFilename( char *fileName, BOOLEAN isUnicode )
  181.     {
  182.     int fileNameFieldLen = screenWidth - 53;    /* Width of fileName field */
  183.     int fileNameLen, maxFileNameLen;
  184.     static char formattedFileName[ 128 ];
  185.  
  186.     /* If it's a Unicode filename, at the moment just return an indicator of
  187.        this fact (virtually no OS's support this yet) */
  188.     if( isUnicode )
  189.         return( "<Unicode>" );
  190.  
  191.     /* Get filename, truncate if overly long, and add end marker */
  192.     fileNameLen = strlen( fileName );
  193.     maxFileNameLen = ( fileNameLen > fileNameFieldLen ) ? fileNameFieldLen : fileNameLen;
  194.     strncpy( formattedFileName, fileName, maxFileNameLen );
  195.     if( fileNameLen > fileNameFieldLen )
  196.         strcpy( &formattedFileName[ fileNameFieldLen - 2 ], ".." );
  197.     else
  198.         formattedFileName[ maxFileNameLen ] = '\0';
  199.  
  200.     return( formattedFileName );
  201.     }
  202.  
  203. /* Display information on one file */
  204.  
  205. static void showFileInfo( const FILEHDRLIST *fileInfoPtr, LONG *totalLength, \
  206.                           LONG *totalSize )
  207.     {
  208.     const FILEHDR *theHeader = &fileInfoPtr->data;
  209.     int time1, time2, time3, hours, minutes, seconds;
  210.     BYTE cryptInfo = ( theHeader->archiveInfo & ARCH_EXTRAINFO ) ? \
  211.             *fileInfoPtr->extraInfo & ( EXTRA_SECURED | EXTRA_ENCRYPTED ) : 0;
  212.     int ratio;
  213.  
  214.     /* Handle file, data lengths and compression ratios.  The check for
  215.        fileLen > dataLen is necessary since we may end up expanding the
  216.        data when we append the checksum to the end */
  217.     *totalLength += theHeader->fileLen;
  218.     *totalSize += theHeader->dataLen;
  219. #ifdef __MSDOS__
  220.     ratio = getRatio( theHeader->fileLen, theHeader->dataLen );
  221. #else
  222.     if( theHeader->fileLen && theHeader->fileLen > theHeader->dataLen )
  223.         ratio = 100 - ( int ) ( ( 100 * theHeader->dataLen ) / theHeader->fileLen );
  224.     else
  225.         ratio = 0;
  226. #endif /* __MSDOS__ */
  227.  
  228.     /* Set up the date fields */
  229.     extractDate( theHeader->fileTime, &time1, &time2, &time3, \
  230.                                       &hours, &minutes, &seconds );
  231.  
  232.     hprintf( VIEWFILE_MAIN_DISPLAY, \
  233.              ( ( theHeader->archiveInfo & ARCH_SYSTEM ) >= OS_UNKNOWN ) ? \
  234.                 systemName[ OS_UNKNOWN ] : \
  235.                 systemName[ theHeader->archiveInfo & ARCH_SYSTEM ], \
  236.              theHeader->fileLen, theHeader->dataLen, ratio, \
  237.              time1, time2, time3, hours, minutes, seconds, \
  238.              ( cryptInfo == ( EXTRA_ENCRYPTED | EXTRA_SECURED ) ) ? '#' : \
  239.                 ( cryptInfo == EXTRA_ENCRYPTED ) ? '*' : \
  240.                 ( cryptInfo == EXTRA_SECURED ) ? '-' : ' ', \
  241.              formatFilename( fileInfoPtr->fileName, \
  242.                              ( fileInfoPtr->extraInfo != NULL ) && \
  243.                              ( *fileInfoPtr->extraInfo & EXTRA_UNICODE ) ) );
  244.     }
  245.  
  246. /* The size of the directory stack.  We should never have more than 50
  247.    directories in one pathname */
  248.  
  249. #define DIRSTACK_SIZE    50
  250.  
  251. /* Display information on one directory */
  252.  
  253. void showDirPath( WORD dirNo )
  254.     {
  255.     WORD dirStack[ DIRSTACK_SIZE ];
  256.     int time1, time2, time3, hours, minutes, seconds;
  257.     int stackIndex = 0;
  258.     char *dirName;
  259.  
  260.     /* Print the directory info if necessary */
  261.     if( dirNo )
  262.         {
  263.         hprintf( MESG_DIRECTORY );
  264.         extractDate( getDirTime( dirNo ), &time1, &time2, &time3, &hours, &minutes, &seconds );
  265.  
  266.         /* Get chain of directories from root to current directory.  Some of
  267.            this code is duplicated in getPath(), but we can't use getPath()
  268.            since it munges the pathName into an OS-compatible format as it goes */
  269.         do
  270.             dirStack[ stackIndex++ ] = dirNo;
  271.         while( ( dirNo = getParent( dirNo ) ) && stackIndex <= DIRSTACK_SIZE );
  272.  
  273.         /* Now print full path to current directory */
  274.         while( stackIndex )
  275.             {
  276.             dirName = getDirName( dirStack[ --stackIndex ] );
  277.             hprintf( "/%s", dirName );
  278.             }
  279.  
  280.         /* Finally, print the directory date */
  281.         hprintf( MESG_DIRECTORY_TIME, time1, time2, time3, hours, minutes, seconds );
  282.         }
  283.  
  284.     /* Make sure we don't get a "Nothing to do" error if we elect to view
  285.        only (empty) directories */
  286.     if( viewFlags & VIEW_DIRS )
  287.         archiveChanged = TRUE;
  288.     }
  289.  
  290. /* Static vars for tracking totals when multiple archives are used */
  291.  
  292. static LONG grandTotalLength = 0L, grandTotalSize = 0L;
  293. static int grandTotalFiles = 0, totalArchives = 0;
  294.  
  295. /* Display a directory of files within an archive */
  296.  
  297. void listFiles( void )
  298.     {
  299.     FILEHDRLIST *fileInfoPtr;
  300.     DIRHDRLIST *dirInfoPtr;
  301.     FILEHDR theHeader;
  302.     LONG totalLength = 0L, totalSize = 0L;
  303.     int fileCount = 0, totalRatio;
  304.     int time1, time2, time3, hours, minutes, seconds;
  305.     WORD oldFlags, hType, count;
  306.     BOOLEAN showFile, dirNameShown;
  307.  
  308.     /* Turn on stealth mode to disable printing of any extraneous noise
  309.        while extracting data.  This is safe since the view options don't
  310.        check for stealth mode */
  311.     flags |= STEALTH_MODE;
  312.  
  313.     /* Print a newline if there is an archive listing preceding this one */
  314.     if( totalArchives )
  315.         hputchar( '\n' );
  316.  
  317.     hputs( VIEWFILE_TITLE );
  318.  
  319.     for( count = getFirstDir(); count != END_MARKER; count = getNextDir() )
  320.         {
  321.         /* First handle any special entries (if there are any and provided
  322.            it's not a multipart archive) */
  323.         if( ( fileInfoPtr = getFirstFileEntry( count ) ) != NULL && \
  324.             !( flags & MULTIPART_ARCH ) )
  325.             do
  326.                 {
  327.                 /* Check whether this is an archive comment file, unless
  328.                    we've been asked to diaply comment files only */
  329.                 if( !( flags & ARCH_COMMENT ) && \
  330.                     ( ( hType = fileInfoPtr->hType ) == TYPE_COMMENT_TEXT || \
  331.                         hType == TYPE_COMMENT_ANSI ) )
  332.                     {
  333.                     /* Move to the comment data */
  334.                     theHeader = fileInfoPtr->data;
  335.                     vlseek( fileInfoPtr->offset, SEEK_SET );
  336.                     resetFastIn();
  337.                     oldFlags = flags;
  338.  
  339.                     /* Set up any handlers we need for it */
  340.                     switch( hType )
  341.                         {
  342.                         case TYPE_COMMENT_TEXT:
  343.                             /* Set up system for text output */
  344.                             setOutputIntercept( OUT_FMT_TEXT );
  345.                             if( !( flags & XLATE_OUTPUT ) )
  346.                                 {
  347.                                 /* Turn on smart translation if none is
  348.                                    specified */
  349.                                 flags |= XLATE_OUTPUT;
  350.                                 xlateFlags = XLATE_SMART;
  351.                                 }
  352.                             break;
  353.  
  354.                         case TYPE_COMMENT_ANSI:
  355.                             /* Output it raw (assumes ANSI driver) */
  356.                             setOutputFD( STDOUT );
  357.                             break;
  358.  
  359.                         default:
  360.                             /* Don't know what to do with it, send it to the
  361.                                bit bucket */
  362.                             setOutputIntercept( OUT_NONE );
  363.                         }
  364.  
  365.                     /* Call extractData() to move the comment to wherever
  366.                        it's meant to go */
  367.                     extractData( theHeader.archiveInfo, 0, theHeader.dataLen, \
  368.                                  theHeader.fileLen, FALSE );
  369.  
  370.                     /* Reset status of output handlers */
  371.                     flags = oldFlags;
  372.                     resetOutputIntercept();
  373.                     archiveChanged = TRUE;
  374.                     }
  375.                 }
  376.             while( ( fileInfoPtr = getNextFileEntry() ) != NULL );
  377.  
  378.         dirNameShown = FALSE;    /* Haven't printed dir.name yet */
  379.  
  380.         /* First print any subdirectories */
  381.         if( !( viewFlags & VIEW_FILES ) )
  382.             if( ( dirInfoPtr = getFirstDirEntry( count ) ) != NULL )
  383.                 do
  384.                     if( getDirTaggedStatus( dirInfoPtr->dirIndex ) )
  385.                         {
  386.                         /* Print the path to the directory if necessary */
  387.                         if( !dirNameShown )
  388.                             {
  389.                             showDirPath( count );
  390.                             dirNameShown = TRUE;
  391.                             }
  392.  
  393.                         extractDate( dirInfoPtr->data.dirTime, &time1, &time2, &time3, &hours, &minutes, &seconds );
  394.                         hprintf( VIEWFILE_SUBDIRECTORY, time1, time2, time3, \
  395.                                  hours, minutes, seconds, \
  396.                                  formatFilename( dirInfoPtr->dirName, \
  397.                                                  dirInfoPtr->data.dirInfo & DIR_UNICODE ) );
  398.                         archiveChanged = TRUE;
  399.                         }
  400.                 while( ( dirInfoPtr = getNextDirEntry() ) != NULL );
  401.  
  402.         /* Then print the files in the directory */
  403.         if( !( viewFlags & VIEW_DIRS ) )
  404.             {
  405.             /* Sort the files if necessary */
  406.             if( viewFlags & VIEW_SORTED )
  407.                 sortFiles( count );
  408.  
  409.             if( ( fileInfoPtr = getFirstFileEntry( count ) ) != NULL )
  410.                 do
  411.                     {
  412.                     /* Exclude either special-format files by default, or non-comment
  413.                        files if asked to display only comment files */
  414.                     if( flags & ARCH_COMMENT )
  415.                         showFile = ( hType = fileInfoPtr->hType ) == TYPE_COMMENT_TEXT || \
  416.                                      hType == TYPE_COMMENT_ANSI;
  417.                     else
  418.                         showFile = ( !( fileInfoPtr->data.archiveInfo & ARCH_SPECIAL ) );
  419.  
  420.                     if( showFile && fileInfoPtr->tagged )
  421.                         {
  422.                         /* Print the path to the directory if necessary */
  423.                         if( !dirNameShown )
  424.                             {
  425.                             showDirPath( count );
  426.                             dirNameShown = TRUE;
  427.                             }
  428.  
  429.                         archiveChanged = TRUE;    /* We've accessed the archive */
  430.                         showFileInfo( fileInfoPtr, &totalLength, &totalSize );
  431.                         fileCount++;
  432.                         }
  433.                     }
  434.                 while( ( fileInfoPtr = getNextFileEntry() ) != NULL );
  435.             }
  436.         }
  437.  
  438.     /* Print summary of file info */
  439. #ifdef __MSDOS__
  440.     totalRatio = getRatio( totalLength, totalSize );
  441. #else
  442.     if( totalLength && totalLength > totalSize )
  443.         totalRatio = 100 - ( int ) ( ( 100 * totalSize ) / totalLength );
  444.     else
  445.         totalRatio = 0;
  446. #endif /* __MSDOS__ */
  447.  
  448.     hprintf( VIEWFILE_TRAILER, totalLength, totalSize, ( int ) totalRatio, \
  449.              fileCount, ( fileCount == 1 ) ? MESG_SINGULAR_FILES : \
  450.                                               MESG_PLURAL_FILES );
  451.  
  452.     /* Update grand totals */
  453.     grandTotalLength += totalLength;
  454.     grandTotalSize += totalSize;
  455.     grandTotalFiles += fileCount;
  456.     totalArchives++;
  457.     }
  458.  
  459. /* Print summary of archives viewed if necessary */
  460.  
  461. void showTotals( void )
  462.     {
  463.     if( totalArchives > 1 )
  464.         hprintf( VIEWFILE_GRAND_TOTAL, \
  465.                  grandTotalLength, grandTotalSize, totalArchives, \
  466.                  grandTotalFiles, \
  467.                  ( grandTotalFiles == 1 ) ? MESG_SINGULAR_FILES : \
  468.                                              MESG_PLURAL_FILES );
  469.     }
  470.